from flask import render_template, request, session, jsonify, Response, make_response
from aps import app
from sqlalchemy import and_
import webbrowser
from aps.models.proyecto import *
from aps.models.usuario import *
from aps.models.proyectorol import *
from aps.models.proyectousuario import *
from aps.models.proyectousuariorol import *
from aps.models import *
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm


@app.route('/crear_proyecto', methods=['GET', 'POST']) 
def crear_proyecto():
    """
    Nos permite traer los parametros que fueron cargados por el usuario
    y guardarlos en la base de datos.
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """ 
    id_usuario    = request.form['id_usuario']
    nombre        = request.form['nombre']
    descripcion   = request.form['descripcion']
    fechainicio   = '0001-01-01'
    fechafin      = '0001-01-01'
    estado        = 'NO-INICIADO'
    complejidadtotal = 0
    nfases        = 0 
    observaciones = request.form['observaciones']
    #with transaction.manager:
    
    model         = Proyecto(nombre, descripcion, fechainicio, fechafin, estado, nfases, complejidadtotal, observaciones)
    bdsession.add(model)
    
    proyecto =  bdsession.query(Proyecto).filter_by(nombre=nombre).first()
    id_proyecto = proyecto.id
    
    proyecto.usuarios.append(ProyectoUsuario(id_proyecto, id_usuario))
    proyecto.usuarios_x_rol.append(ProyectoUsuarioRol(id_proyecto,id_usuario, 2 ))
    proyecto.roles.append(ProyectoRol(id_proyecto,2))
    
    #Se asigna al comite al lider
    usuario_comite=bdsession.query(ProyectoUsuario).filter_by(idproyecto=id_proyecto,idusuario=id_usuario).first()
    usuario_comite.comite=1
    
    proyecto.usuarios_x_rol.append(ProyectoUsuarioRol(id_proyecto,id_usuario, 3 ))
    proyecto.roles.append(ProyectoRol(id_proyecto,3))
    
    bdsession.merge(proyecto)
    return jsonify ({'success' : True})

@app.route('/modificar_proyecto', methods=['GET', 'POST']) 
def modificar_proyecto():
    """
    Nos permite traer los parametros que fueron modificados por el usuario
    y guardar los cambios en la base de datos.
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """ 
    id            = request.form['id']
    nombre        = request.form['nombre']
    descripcion   = request.form['descripcion']
    fechainicio   = request.form['fechainicio']
    fechafin      = request.form['fechafin']
    estado        = request.form['estado']
    observaciones = request.form['observaciones']
    proyecto = bdsession.query(Proyecto).filter_by(id=id).first()
    # se modifica en la BD
    model         = Proyecto(nombre, descripcion, fechainicio, fechafin, estado, proyecto.nfases, proyecto.complejidadtotal, observaciones)
    model.id      = id
    bdsession.merge(model)
    return jsonify ({'success' : True})

@app.route('/eliminar_proyecto', methods=['GET', 'POST']) 
def eliminar_proyecto():
    """
    Nos permite traer el id del proyecto a eliminar, eliminar las dependendcias
    del mismo con respecto a otras tablas y eliminar el registro de la base de datos.
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente y False en caso contrario
    """    
    id       = request.form['id']
    proyecto = bdsession.query(Proyecto).filter_by(id=id).first()
    if proyecto is None:
        return jsonify ({'success':False})
    proyecto.eliminar_dependencias()
    bdsession.refresh(proyecto)
    bdsession.delete(proyecto)
    return jsonify ({'success' : True})

@app.route('/iniciar_proyecto', methods=['GET', 'POST']) 
def iniciar_proyecto():
    """
    Nos permite iniciar un proyecto siempre y cuando tenga al menos una fase.
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente y False en caso contrario
    """    
    id_proyecto = request.form['id_proyecto']
    proyecto = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    if len(proyecto.fases) != 0:
        proyecto.estado = 'INICIADO'
        bdsession.merge(proyecto)
        return jsonify ({'success': True})
    else:
        return jsonify ({'success': False})
        
@app.route('/terminar_proyecto', methods=['GET', 'POST']) 
def terminar_proyecto():
    """
    Nos permite terminar un proyecto siempre y cuando todas sus fases esten terminadas.
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente y False en caso contrario
    """    
    id_proyecto = request.form['id_proyecto']
    proyecto = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    lista   = proyecto.fases
    lista   = [ p for p in lista if p.fase.estado == u'FINALIZADO']
    if proyecto.nfases == len(lista):
        proyecto.estado = 'FINALIZADO'
        bdsession.merge(proyecto)
        return jsonify ({'success':True})
    else:
        return jsonify ({'success':False})


@app.route('/consultar_proyecto') 
def consultar_proyecto():
    """
    Nos permite traer los parametros de consulta(el filtro y el valor) y mostrar
    los proyectos que cumplen con la condicion del filtro.
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    proyectos = None
    if not request.args.has_key('id_proyecto'):
        if request.args.has_key('filtro'):
            filtro    = request.args['filtro']
            valor     = request.args['valor']
            sentencia = 'SELECT * from Proyecto WHERE {0}=\'{1}\''.format(filtro,valor)
            proyectos  = bdsession.query(Proyecto).from_statement(sentencia).all()
        else:
            proyectos = bdsession.query(Proyecto).all()
    else:
        id_proyecto   = request.args['id_proyecto']
        if request.args.has_key('filtro'):
            filtro    = request.args['filtro']
            valor     = request.args['valor']
            sentencia = 'SELECT * from Proyecto WHERE id={0} and {1}=\'{2}\''.format(id_proyecto, filtro, valor)
            proyectos  = bdsession.query(Proyecto).from_statement(sentencia).all()
        else:
            sentencia  = 'SELECT * from Proyecto WHERE id={0}'.format(id_proyecto)
            proyectos  = bdsession.query(Proyecto).from_statement(sentencia).all()
         
    proyectos = [ p for p in proyectos if p.estado != u'ELIMINADO' and p.id != 1]
    data = []
    for proyecto in proyectos:
        item = {}
        item['id'] = proyecto.id
        item['nombre'] = proyecto.nombre
        item['descripcion'] = proyecto.descripcion
        item['fechainicio'] = str(proyecto.fechainicio)
        item['fechafin'] = str(proyecto.fechafin)
        item['estado'] = proyecto.estado
        data.append(item)
    return jsonify ({'success':True, 'data':data, 'total':len(data)})

@app.route('/asignar_usuario_rol_proyecto', methods=['GET', 'POST']) 
def asignar_usuario_rol_proyecto():
    """
    Nos permite realizar la asignacion de un usuario a un proyecto
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    # id del proyecto al que se le asigna un usuario
    id_proyecto = request.form['id_proyecto']
    # id del usuario a asignar
    id_usuario  = request.form['id_usuario']
    # lista de id de roles del usuario en el proyecto
    id_roles    = eval(request.form['id_roles'])
    
    # obtenemos el proyecto desde la BD
    proyecto = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    # eliminamos las relaciones con el usuario en la tabla 'proyectousuario'
    bdsession.query(ProyectoUsuario).filter_by(idproyecto=id_proyecto,idusuario=id_usuario).delete(synchronize_session=False)
    # eliminamos las relaciones con el usuario en la tabla 'proyectousuariorol'
    bdsession.query(ProyectoUsuarioRol).filter_by(idproyecto=id_proyecto,idusuario=id_usuario).delete(synchronize_session=False)
    # actualizamos el proyecto
    bdsession.refresh(proyecto)
    # creamos una nueva asignacion proyecto-usuario en la tabla 'proyectousuario'
    proyecto.usuarios.append(ProyectoUsuario(id_proyecto, id_usuario))
    # creamos una nueva lista de usuarios asignados (con sus roles) al proyecto en la tabla 'proyectousuariorol'
    for id_rol in id_roles:
        proyecto.usuarios_x_rol.append(ProyectoUsuarioRol(id_proyecto,id_usuario, id_rol))
    
    # guardamos los cambios
    bdsession.merge(proyecto)
    return jsonify ({'success':True})

@app.route('/desasignar_usuario_rol_proyecto', methods=['GET', 'POST']) 
def desasignar_usuario_rol_proyecto():
    """
    Nos permite realizar la desasignacion de un usuario de un proyecto
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """

    usuario_actual       = bdsession.query(Usuario).filter_by(nick=session['usuario']).first()
    id_proyecto_actual   = int(request.form['id_proyecto_actual'])
    id_proyecto_asignado = int(request.form['id_proyecto_asignado'])
    id_usuario           = int(request.form['id_usuario'])
     
    # Comprobamos que no tratemos de desasignarnos de nuestro proyecto actual
    if id_proyecto_asignado == id_proyecto_actual and usuario_actual.id == id_usuario:
        # imposible de desasignar al usuario
        return jsonify ({'success':False})
    
    miembro= bdsession.query(ProyectoUsuario).filter_by(idproyecto=id_proyecto_asignado,idusuario=id_usuario).first()
    if miembro.comite==1: 
        return jsonify ({'success':False})
    else:
        # podemos desasignar al usuario
        # eliminamos las relaciones con el usuario en la tabla 'proyectousuario'
        bdsession.query(ProyectoUsuario).filter_by(idproyecto=id_proyecto_asignado,idusuario=id_usuario).delete(synchronize_session=False)
        # eliminamos las relaciones con el usuario en la tabla 'proyectousuariorol'
        bdsession.query(ProyectoUsuarioRol).filter_by(idproyecto=id_proyecto_asignado,idusuario=id_usuario).delete(synchronize_session=False)       
        return jsonify ({'success':True})
 
@app.route('/consulta_rol_x_proyecto') 
def consulta_rol_x_proyecto():
    """
    Nos permite obtener la lista detallada de roles dentro de un proyecto
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    id_proyecto = request.args['idproyecto']
    proyecto    = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    data = []
    for rol in proyecto.roles:
        if rol.rol.id > 3:
            item = {}
            item['id']          = rol.rol.id
            item['nombre']      = rol.rol.nombre
            item['descripcion'] = rol.rol.descripcion
            data.append(item)
    return jsonify ({'success':True, 'data':data, 'total':len(data)})
 
@app.route('/consulta_usuario_x_proyecto', methods=['GET', 'POST']) 
def consulta_usuario_x_proyecto():
    """
    Nos permite obtener la lista detallada de usuarios dentro de un proyecto
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    id_proyecto = request.args['idproyecto']
    proyecto    = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    data = []
    for usuario in proyecto.usuarios:
        item = {}
        item['id']      = usuario.usuario.id
        item['ci']      = usuario.usuario.ci
        item['nick']    = usuario.usuario.nick
        item['nombres']    = usuario.usuario.nombres
        item['apellidos']    = usuario.usuario.apellidos
        item['direccion']    = usuario.usuario.direccion
        item['email']    = usuario.usuario.email
        data.append(item)
    return jsonify ({'success':True, 'data':data, 'total':len(data)})
 
 
@app.route('/consulta_proyecto_combo', methods=['GET', 'POST']) 
def consulta_proyecto_combo():
    """
    Nos permite obtener la lista de proyectos del sistema
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    proyectos   = None
    sentencia  = 'SELECT * from Proyecto WHERE id != {0}'.format(1)
    proyectos  = bdsession.query(Proyecto).from_statement(sentencia).all()
    data = []
    for proyecto in proyectos:
        item = {}
        item['id'] = proyecto.id
        item['nombre'] = proyecto.nombre
        data.append(item)
    return jsonify ({'total':len(data), 'data':data})
 
@app.route('/generar_informe_proyecto', methods=['GET', 'POST']) 
def generar_informe_proyecto():
    id_proyecto = request.form['idproyecto']
    proyecto = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    # Obtenemos la informacion a utilizar como entrada del informe
    info = proyecto.get_info()
    # Procesamos los datos y generamos el archivo .pdf
#    factory  = ReportFactory()
#     template = 'aps/templates/informe.xml'
#     factory.render_template(template_file=template,proyecto=info['proyecto'],miembros=info['miembros'],roles=info['roles'],fases=info['fases'],fase_x=info['fase_x'])
#     factory.render_document('/tmp/test.pdf')
#     factory.cleanup()
    # Obtenemos el contenido del archivo generado
    informe = open('/tmp/test.pdf','rb')
    informe.seek(0)
    data = ''
    while 1:
        tmp = informe.read(1024)
        if not tmp:
            break
        data = data + tmp
    informe.close()
    # Enviamos el informe al cliente
    resp  = Response(content_type='application/pdf')
    resp._headerlist.append(('Content-Length',str(len(data))))
    resp.body = data
     
    return resp

@app.route('/consulta_rol_x_usuario', methods=['GET', 'POST']) 
def consulta_rol_x_usuario():
    """
    Nos permite obtener la lista detallada de roles que pertenecen a un usuario dentro de un proyecto
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    id_proyecto = request.args['id_proyecto']
    id_usuario = request.args['id_usuario']
    print id_proyecto
    print id_usuario
    
#     proyecto    = bdsession.query(Proyecto,ProyectoUsuario).\
#                     filter(Proyecto.id==id_proyecto).\
#                     filter(ProyectoUsuario.idusuario==id_usuario).all()
    proyecto    = bdsession.query(ProyectoUsuarioRol).filter(and_(ProyectoUsuarioRol.idproyecto== id_proyecto, ProyectoUsuarioRol.idusuario== id_usuario)).first()
    roles = bdsession.query(Rol).filter_by(id=proyecto.idrol).all()
    for rol in roles:
        print rol.nombre
        data = []
        #if rol.id > 2: 
        item = {}
        item['id']          = rol.id
        item['nombre']      = rol.nombre
        item['descripcion'] = rol.descripcion
        data.append(item)
    return jsonify ({'success':True, 'data':data, 'total':len(data)})


@app.route('/asignar_usuario_proyecto_comite', methods=['GET', 'POST']) 
def asignar_usuario_proyecto_comite():
    """
    Nos permite realizar la asignacion de un usuario a un proyecto
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    received   = eval(request.form['data'])
    
    
    # ids de usuarios asignados
    data   = received['data']
    # id del proyecto al que se le asigna un usuario
    id_proyecto = received['id_proyecto']
    
    # comprobamos que no exista ninguna solicitud pendiente de voto para poder modificar el comite
    sentencia      = 'SELECT * from Fase WHERE id in (SELECT idfase from ProyectoFase WHERE idproyecto={0})'.format(id_proyecto)
    fases = bdsession.query(Fase).from_statement(sentencia).all()
    solicitudes = None
    for fase in fases:
        solicitudes = bdsession.query(Solicitud).filter(Solicitud.idfase==fase.id, Solicitud.estado =='ENVIADA').first()
        if solicitudes is not None:
            return jsonify(success=False)
     # elimiminamos todos los miembros del comite para volver a reemplazar
    usuarios = bdsession.query(ProyectoUsuario).filter_by(idproyecto=id_proyecto).all()
    proyecto = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    for usuario_comite in usuarios:
        usuario_comite.comite=0
        
        # podemos desasignar al usuario
        # eliminamos las relaciones con el usuario en la tabla 'proyectousuario'
#         bdsession.query(ProyectoUsuario).filter_by(idproyecto=id_proyecto,idusuario=usuario_comite.idusuario).delete(synchronize_session=False)
        # eliminamos las relaciones con el usuario en la tabla 'proyectousuariorol'
        bdsession.query(ProyectoUsuarioRol).filter_by(idproyecto=id_proyecto,idusuario=usuario_comite.idusuario, idrol =3).delete(synchronize_session=False)       
        bdsession.refresh(proyecto)
        
    # marcamos los usuarios como miembros del comite
    for idusuario in data:    
        proyecto.usuarios_x_rol.append(ProyectoUsuarioRol(id_proyecto,idusuario, 3 ))

#         bdsession.flush()
        usuario_comite=bdsession.query(ProyectoUsuario).filter_by(idproyecto=id_proyecto,idusuario=idusuario).first()
        usuario_comite.comite=1

    # guardamos los cambios
    bdsession.merge(proyecto)
    return jsonify ({'success':True})
@app.route('/consulta_usuario_x_proyecto_comite', methods=['GET', 'POST']) 
def consulta_usuario_x_proyecto_comite():
    """
    Nos permite obtener la lista detallada de usuarios dentro de un proyecto
    @param  request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    id_proyecto = request.args['idproyecto']
    proyecto    = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    sentencia='select * from Usuario where id  in (select idusuario from ProyectoUsuario where idproyecto=\'{0}\' and comite=1)'
    usuarios_asignados = bdsession.query(Usuario).from_statement(sentencia.format(id_proyecto)).all()
    data = []
    for usuario in usuarios_asignados:
        item = {}
        item['id']      = usuario.id
        item['ci']      = usuario.ci
        item['nick']    = usuario.nick
        item['nombres']    = usuario.nombres
        item['apellidos']    = usuario.apellidos
        item['direccion']    = usuario.direccion
        item['email']    = usuario.email
        data.append(item)
    return jsonify ({'success':True, 'data':data, 'total':len(data)})
@app.route('/crear_informe_solicitud', methods=['GET', 'POST']) 
def crear_informe_solicitud():
    id_proyecto = request.form['idproyecto']
    nombrepdf = "/tmp/Historial_Solicutud_de_cambio_proyecto" + str(id_proyecto) + ".pdf"
    nombre = "Historial_Solicutud_de_cambio_proyecto" + str(id_proyecto) + ".pdf"
    c = canvas.Canvas(nombrepdf)
    c.setTitle("Historial de solicitud de cambios")
    a = 28
    #recorrer por id_solicitud
    solicitudes = bdsession.query(HistorialSolicitud).filter_by(idproyecto=id_proyecto).all()
    for sol in solicitudes:
        s = bdsession.query(HistorialSolicitud).filter_by(idsolicitud=sol.idsolicitud).all()
        c.line(1*cm,a*cm,19*cm,a*cm)
        a=a-0.5
        escribir = ""
        band = True
        for solicitud in s:
            escribir = "Linea Base: " + str(solicitud.idlineabase)
            c.setFont("Helvetica-Bold", 10)
            c.drawString(1*cm, a*cm,escribir)
            a = a - 0.5
            escribir = "Usuario: " + str(solicitud.idusuario)
            c.drawString(1*cm, a*cm,escribir)
            a = a - 0.5
            escribir = "Mensaje: " + solicitud.mensaje
            c.drawString(1*cm, a*cm,escribir)
            a = a - 0.5
            c.line(1*cm,a*cm,19*cm,a*cm)
            a = a - 0.5
            c.setFont("Helvetica", 10)
            
            if a < 3:
                a = 28
                c.showPage()
                band = True
            if band == True:
                c.setFont("Helvetica-Bold", 10)
                c.drawString(1*cm, 29*cm,"Historial de Solicitud de cambio")
                c.line(1*cm,28.5*cm,19*cm,28.5*cm)
                band = False
    c.save()
    
    response = make_response()
    response.headers['Content-Type'] = 'application/pdf'
    response.headers['Content-Disposition'] = 'filename='+ nombrepdf
    response.headers['Cache-Control'] = 'no-cache'
    
   
    f = open(nombrepdf, 'r')
    response.headers['Content-Length'] = str(f.__sizeof__())
    response.data=f.read()
    webbrowser.open(nombrepdf)
    
@app.route('/crear_informe', methods=['GET', 'POST']) 
def crear_informe():
    id_proyecto = request.form['idproyecto']
    nombrepdf = "/tmp/Informe_Proyecto_" + str(id_proyecto) + ".pdf"
    nombre = "Informe_Proyecto_" + str(id_proyecto) + ".pdf"
    c = canvas.Canvas(nombrepdf)
    c.setTitle("Historial de Items por Fase")
    a = 28.5
    band = True
    fases = bdsession.query(ProyectoFase).filter_by(idproyecto=id_proyecto).all()
    for fase in fases:
        f = bdsession.query(Fase).filter_by(id=fase.idfase).first()
        c.line(1*cm,a*cm,19*cm,a*cm)
        a=a-0.5
        escribir = "Fase: " + f.nombre + "    -    " + "Id: " + str(f.id) 
        c.setFont("Helvetica-Bold", 10)
        c.drawString(1*cm, a*cm,escribir)
        a = a - 0.5
        c.line(1*cm,a*cm,19*cm,a*cm)
        a = a - 0.5
        c.setFont("Helvetica", 10)
        items = bdsession.query(Item).filter_by(idfase=f.id).all()
        
        if a < 3:
            a = 28.5
            c.showPage()
            band = True
        
        if band == True:
            c.setFont("Helvetica-Bold", 10)
            c.drawString(1*cm, 29*cm,"Historial de Items por Fase")
            c.line(1*cm,28.5*cm,19*cm,28.5*cm)
#             c.line(1*cm,28.4*cm,19*cm,28.4*cm)
            band = False

        for item in items:
            c.setFont("Helvetica", 10)
            escribir = "Id: " + str(item.id)
            c.drawString(1*cm, a*cm,escribir)
            a = a - 0.5
            escribir = "Nombre: " + item.nombre
            c.drawString(1*cm, a*cm,escribir)
            a = a - 0.5
            escribir = "Version: " + str(item.version)
            c.drawString(1*cm, a*cm,escribir)
            a = a - 0.5
            escribir = "Costo: " + str(item.complejidad)
            c.drawString(1*cm, a*cm,escribir)
            a = a - 1
            if a < 3:
                a = 28.5
                c.showPage()
                band = True
        
            if band == True:
                c.setFont("Helvetica-Bold", 10)
                c.drawString(1*cm, 29*cm,"Historial de Items por Fase")
                c.line(1*cm,28.5*cm,19*cm,28.5*cm)
                band = False
            
    c.save()
    
    response = make_response()
    response.headers['Content-Type'] = 'application/pdf'
    response.headers['Content-Disposition'] = 'filename='+ nombrepdf
    response.headers['Cache-Control'] = 'no-cache'
    
   
    f = open(nombrepdf, 'r')
    response.headers['Content-Length'] = str(f.__sizeof__())
    response.data=f.read()
    webbrowser.open(nombrepdf)
    return response